//
// Created by Crestimes on 24-5-9.
//

#ifndef TOKEN_H
#define TOKEN_H
#include <map>
#include <string>


typedef enum {
    // 正则表达式相关
    RE_LEFT_FLAG, // $
    RE_RIGHT_FLAG, // $
    RE_CHAR, // 除了正则表达式中所用到的符号外的任意字符
    RE_CONCAT, // & (可能用不到)
    RE_OR, // |
    RE_ZERO_OR_MORE, // # (*)
    RE_ZERO_OR_ONE, // ?
    RE_ONE_OR_MORE, // +
    RE_ANY, // .
    RE_LEFT_SMALL, // (
    RE_RIGHT_SMALL, // )
    RE_LEFT_MID, // [
    RE_RIGHT_MID, // ]
    RE_LINE_IN_MID, // []中间的-
    RE_CHAR_BEFORE_LINE, // -前面的字符，作为标记

    // 算术表达式相关
    OP_CAMP, // 比较符号 = <= < <> > >=
    OP_LEVEL0, // 优先级0运算符号 + -
    OP_LEVEL1, // 优先级1运算符号 * / %
    OP_LEVEL2, // 优先级2运算符号 ^
    OP_SELF, // 单目运算符 -- ++
    NUMBER, // 数字
    IDENTIFIER, // 变量
    LEFT_SMALL, // (
    RIGHT_SMALL, // )
    LEFT_MID, // [
    RIGHT_MID, // ]

    // 关键字
    IF,
    ELSE,
    REPEAT,
    UNTIL,
    READ,
    WRITE,
    WHILE,
    ENDWHILE,
    FOR,

    // 其他符号
    REG_EQ, // ==
    EXP_EQ, // :=
    STMT_END, // ;
    IGNORE, // 注释
    END, // 结束
} TokenType;


inline std::map<std::string, TokenType> keyWord2tokenType = {
    {"if", IF},
    {"else", ELSE},
    {"repeat", REPEAT},
    {"until", UNTIL},
    {"read", READ},
    {"write", WRITE},
    {"while", WHILE},
    {"endwhile", ENDWHILE},
    {"for", FOR},
};

inline std::map<char, TokenType> token2tokenType = {
    // 没有+ - =之类的是因为这些符号有多种情况，会进INXXX判断，不会进用到该映射的判断
    {'(', LEFT_SMALL},
    {')', RIGHT_SMALL},
    {'[', LEFT_MID},
    {']', RIGHT_MID},
    {'*', OP_LEVEL1},
    {'/', OP_LEVEL1},
    {'%', OP_LEVEL1},
    {'^', OP_LEVEL2},
    {';', STMT_END},
};

// 正则的符号有不同的意义，在这里单独映射
inline std::map<char, TokenType> regToken2tokenType = {
    {'|', RE_OR},
    {'&', RE_CONCAT},
    {'#', RE_ZERO_OR_MORE},
    {'?', RE_ZERO_OR_ONE},
    {'(', RE_LEFT_SMALL},
    {')', RE_RIGHT_SMALL},
    {'[', RE_LEFT_MID},
    {']', RE_RIGHT_MID},
    {'+', RE_ONE_OR_MORE},
    {'-', RE_LINE_IN_MID},
    {'.', RE_ANY},
    {'*', RE_ZERO_OR_MORE},
};

inline std::map<TokenType, std::string> tokenType2str = {
    {RE_LEFT_FLAG, "re-left-flag"},
    {RE_RIGHT_FLAG, "re-right-flag"},
    {RE_CHAR, "re-char"},
    {RE_CONCAT, "re-concat"},
    {RE_OR, "re-or"},
    {RE_ZERO_OR_MORE, "re-zero-or-more"},
    {RE_ZERO_OR_ONE, "re-zero-or-one"},
    {RE_ONE_OR_MORE, "re-one-or-more"},
    {RE_ANY, "re-any"},
    {RE_LEFT_SMALL, "re-left-small"},
    {RE_RIGHT_SMALL, "re-right-small"},
    {RE_LEFT_MID, "re-left-mid"},
    {RE_RIGHT_MID, "re-right-mid"},
    {RE_LINE_IN_MID, "re-line-in-mid"},
    {RE_CHAR_BEFORE_LINE, "re-char-before-line"},

    {OP_CAMP, "op-camp"},
    {OP_LEVEL0, "op-level0"},
    {OP_LEVEL1, "op-level1"},
    {OP_LEVEL2, "op-level2"},
    {OP_SELF, "op-self"},
    {NUMBER, "number"},
    {IDENTIFIER, "identifier"},
    {LEFT_SMALL, "left-small"},
    {RIGHT_SMALL, "right-small"},
    {LEFT_MID, "left-mid"},
    {RIGHT_MID, "right-mid"},

    {IF, "if"},
    {ELSE, "else"},
    {REPEAT, "repeat"},
    {UNTIL, "until"},
    {READ, "read"},
    {WRITE, "write"},
    {WHILE, "while"},
    {ENDWHILE, "endwhile"},
    {FOR, "for"},

    {REG_EQ, "reg-eq"},
    {EXP_EQ, "exp-eq"},
    {STMT_END, "stmt-end"},
    {IGNORE, "ignore"},
    {END, "end"}
};


class Token {
public:
    Token(TokenType, std::string);

    TokenType type;
    std::string str;
};


#endif //TOKEN_H
